﻿using System;
using System.IO;
using System.Linq;
using System.Reflection;
using Microsoft.AspNetCore.Mvc;
using Microsoft.OpenApi.Models;
using Swashbuckle.AspNetCore.SwaggerGen;

namespace Microsoft.Extensions.DependencyInjection
{
    public static class SwaggerExtensions
    {
        /// <summary>
        /// 5.0.0-rc8
        /// </summary>
        /// <param name="services"></param>
        public static IServiceCollection AddSwaggerExt(this IServiceCollection services, params string[] xmls)
        {
            services.AddSwaggerGen(option =>
            {
                option.SwaggerDoc("v1", new OpenApiInfo
                {
                    Version = "v1",
                    Title = "接口文档",
                    Description = "HTTP API "
                });

                option.IgnoreObsoleteActions();
                option.IgnoreObsoleteProperties();
                option.DescribeAllParametersInCamelCase();
                var xmlList = xmls.ToList();

                xmlList.Add(Assembly.GetEntryAssembly().GetName().Name + ".xml");
                xmlList.Add("Apps.Shared.Entitys.xml");
                xmlList.Add("Apps.Shared.xml");
                foreach (var xml in xmlList)
                {
                    string filepath = Path.Combine(Directory.GetCurrentDirectory(), xml);
                    if (File.Exists(filepath))
                    {
                        option.IncludeXmlComments(filepath, true);
                    }

                }

                option.OperationFilter<OperationFilter>();

                // Token
                option.AddSecurityDefinition("Bearer", new OpenApiSecurityScheme
                {
                    Description = "Token",
                    Name = "access-token",
                    In = ParameterLocation.Header,
                    Type = SecuritySchemeType.ApiKey
                });
                option.AddSecurityRequirement(new OpenApiSecurityRequirement
                {
                    {
                        new OpenApiSecurityScheme
                        {
                            Reference = new OpenApiReference()
                            {
                                Id = "Bearer",
                                Type = ReferenceType.SecurityScheme
                            }
                        }, Array.Empty<string>()
                    }
                });
            });
            return services;
        }

        class OperationFilter : IOperationFilter
        {
            public void Apply(OpenApiOperation operation, OperationFilterContext context)
            {
                var arr = context.ApiDescription.ParameterDescriptions.Where(a => a.CustomAttributes().Any(a => a is TokenAttribute || a is ObsoleteAttribute)).Select(a => a.Name).ToArray();
                operation.Parameters = operation.Parameters.Where(a => !arr.Contains(a.Name, StringComparer.OrdinalIgnoreCase)).ToList();
            }
        }
    }
}
